# -*- coding:utf-8 -*-
import struct
import functools
import message
import gevent
from gevent.queue import Queue

from .channel import LEN_HEADER

@message.observable
class Transport(object):
    TRANSPORT_DATA = 'abu.rpc.transport.TRANSPORT_DATA'
    def __init__(self, ll_transport):
        self._ll_transport = ll_transport
        self._send_queue = Queue()
        self.buff = ''

        self._lets = [gevent.spawn(self._send_func),
                gevent.spawn(self._recv_func)]

        for let in self._lets:
            let.link(self._close)
    
    def _close(self, _):
        for let in self._lets:
            try:
                let.kill()
            except Exception:
                pass
	def __del__(self):
		print 'transport destroy'

    def getpeername(self):
        return self._ll_transport.getpeername()

    def getsockname(self):
        return self._ll_transport.getsockname()

    def send(self, buff):
        self._send_queue.put(buff)
    
    def recv(self):
#        print 'call recv:', repr(self.buff)
        assert self.buff
        t, self.buff = self.buff, ''
        return t

    def _send_func(self):
#         _send = (self._ll_transport.sendall
#                 if isinstance(self._ll_transport,
#                     gevent.socket.socket)
#                 else self._ll_transport.send)
        while True:
            buff = self._send_queue.get()
            length = struct.pack(LEN_HEADER, len(buff))
#            print 'Transport send:', repr(length + buff)
            self._ll_transport.sendall(length + buff)
    
    def _recv_func(self):
#         _recv = (functools.partial(
#             self._ll_transport.recv, 4096)
#                 if isinstance(self._ll_transport,
#                     gevent.socket.socket)
#                 else self._ll_transport.recv)
        while True:
            self.buff = self._ll_transport.recv(4096)
            if not self.buff:
                break
            self.pub(self.TRANSPORT_DATA)

